﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Xml;
using System.Drawing;
using System.IO;
using System.Threading;

namespace SOMClustering
{
    public delegate void OnProgressDelegate(int max, int value, string message, Bitmap tnl);

    class ImageContainer
    {
        private Thread threadFromDirectory;
        private OnProgressDelegate OnProgressEvent;

        private String dirPath;
        private String thumbnailPath;

        List<ImagePattern> images;
        int patternLength = 0;

        public ImageContainer(int patternLength)
        {
            images = new List<ImagePattern>();
            this.patternLength = patternLength;

            InitThreads();
        }

        public ImageContainer(int patternLength, String thumbnailPath)
        {
            images = new List<ImagePattern>();
            this.patternLength = patternLength;
            this.thumbnailPath = thumbnailPath;

            InitThreads();
        }

        public ImageContainer(int patternLength, int imageCount)
        {
            images = new List<ImagePattern>(imageCount);
            this.patternLength = patternLength;

            InitThreads();
        }

        private void InitThreads()
        {
            ThreadStart threadStart = new ThreadStart(ProcessFolder);
            threadFromDirectory = new Thread(threadStart);
        }

        public int Count
        {
            get
            {
                return images.Count;
            }
        }

        public ImagePattern this[int index]
        {
            get
            {
                if ((index < images.Count) && (index >= 0))
                {
                    return images[index];
                }
                else
                {
                    return null;
                }
            }
            //set { pat[index] = value; }
        }

        public List<ImagePattern> Images
        {
            get
            {
                return images;
            }
        }

        public int PatternLength
        {
            get
            {
                return patternLength;
            }
        }

        public void Add(ImagePattern img)
        {
            images.Add(img);
        }

        public void Remove(ImagePattern img)
        {
            images.Remove(img);
        }

        public void RemoveAt(int index)
        {
            images.RemoveAt(index);
        }

        public void AnalyzeAll()
        {
            foreach (ImagePattern img in images)
            {
                img.Analyze();
            }
        }

        public XmlDocument ToXml()
        {
            XmlDocument imageInfo = new XmlDocument();
            imageInfo.LoadXml("<?xml version=\"1.0\"?>" + "<Images version=\"1.0\" creator=\"SOMClustering\"></Images>");

            XmlNode node = imageInfo.CreateElement("patternLength");
            node.InnerText = patternLength.ToString();
            imageInfo.DocumentElement.AppendChild(node);

            node = imageInfo.CreateElement("imageCount");
            node.InnerText = images.Count.ToString();
            imageInfo.DocumentElement.AppendChild(node);

            XmlNode imageNode;
            XmlNode patternNode;

            XmlNode itemAttr;

            for (int i = 0; i < images.Count; i++)
            {
                imageNode = imageInfo.CreateElement("image");

                itemAttr = imageInfo.CreateAttribute("fileName");
                itemAttr.InnerText = images[i].ImageName;
                imageNode.Attributes.Append((XmlAttribute)itemAttr);

                itemAttr = imageInfo.CreateAttribute("thumbnailName");
                itemAttr.InnerText = images[i].ThumbnailName;
                imageNode.Attributes.Append((XmlAttribute)itemAttr);

                for (int j = 0; j < patternLength; j++)
                {
                    patternNode = imageInfo.CreateElement("pattern");

                    itemAttr = imageInfo.CreateAttribute("index");
                    itemAttr.InnerText = j.ToString();
                    patternNode.Attributes.Append((XmlAttribute)itemAttr);

                    patternNode.InnerText = images[i][j].ToString();

                    imageNode.AppendChild(patternNode);
                }
                imageInfo.DocumentElement.AppendChild(imageNode);
            }


            return imageInfo;
        }

        private void ProcessFolder()
        {
            String[] files = Directory.GetFiles(dirPath, "*.jpg", SearchOption.AllDirectories);
            int fileCount = files.Length;
            for (int i = 0; i < fileCount; i++)
            {
                this.Add(new ImagePattern(files[i]));
                if (OnProgressEvent != null)
                {
                    OnProgressEvent.Invoke(fileCount, i + 1, files[i], this[i].Thumbnail);
                }
            }
        }

        public void FromDirectory(String dirPath, OnProgressDelegate onProgress)
        {
            ThreadStart threadStart = new ThreadStart(ProcessFolder);
            threadFromDirectory = new Thread(threadStart);
            
            OnProgressEvent = onProgress;
            this.dirPath = dirPath;
            images.Clear();

            threadFromDirectory.Start();
        }

        public void FromFile(String imageContainerFileName, OnProgressDelegate onProgress)
        {
            OnProgressEvent = onProgress;

        }

        public void FromXml(XmlDocument imageInfo)
        {
            int imageCount = 0;
            int imageIndex = 0;
            images.Clear();

            foreach (XmlNode node in imageInfo.DocumentElement.ChildNodes)
            {
                switch (node.Name)
                {
                    case "patternLength":
                        patternLength = int.Parse(node.InnerText);
                        break;
                    case "imageCount":
                        imageCount = int.Parse(node.InnerText);
                        break;

                    case "image":
                        Double[] pattern = new Double[patternLength];
                        String imgName, thumbName;
                        imgName = node.Attributes.GetNamedItem("fileName").InnerText;
                        thumbName = node.Attributes.GetNamedItem("thumbnailName").InnerText;
                        Bitmap thumbnail = new Bitmap(thumbnailPath + "\\" + thumbName);
                        foreach (XmlNode pattNode in node.ChildNodes)
                        {
                            int index = int.Parse(pattNode.Attributes.GetNamedItem("index").InnerText);
                            pattern[index] = Double.Parse(pattNode.InnerText);
                        }
                        this.Add(new ImagePattern(pattern, thumbnail, imgName));
                        break;

                    default:
                        break;
                }
            }
        }

        static public String FilePathToName(String filePath)
        {
            int lastEntry = filePath.LastIndexOf('\\');
            return filePath.Remove(0, lastEntry + 1);
        }

        static public String FilePathToDirectory(String filePath)
        {
            int lastEntry = filePath.LastIndexOf('\\');
            return filePath.Remove(lastEntry, filePath.Length - lastEntry);
        }
    }
}